package com.authine.cloudpivot.ext.service.settle;

import com.authine.cloudpivot.ext.dto.base.Ids;
import com.authine.cloudpivot.ext.dto.model.settle.*;
import com.authine.cloudpivot.ext.dto.query.SettleApplyQuery;
import com.authine.cloudpivot.ext.service.account.OrganizationAccountService;
import com.authine.cloudpivot.ext.service.account.impl.OrganizationAccountServiceImpl;
import com.authine.cloudpivot.ext.service.bill.BillService;
import com.authine.cloudpivot.ext.service.bill.impl.BillServiceImpl;
import com.authine.cloudpivot.ext.service.contract.ContractServiceFeeTemplateService;
import com.authine.cloudpivot.ext.service.contract.impl.ContractServiceFeeTemplateServiceImpl;
import com.authine.cloudpivot.ext.service.invoice.InvoiceApplyService;
import com.authine.cloudpivot.ext.service.invoice.InvoiceDetailBillService;
import com.authine.cloudpivot.ext.service.invoice.impl.InvoiceApplyServiceImpl;
import com.authine.cloudpivot.ext.service.invoice.impl.InvoiceDetailBillServiceImpl;
import com.authine.cloudpivot.ext.service.trade.TradeService;
import com.authine.cloudpivot.ext.service.trade.impl.TradeServiceImpl;
import com.authine.cloudpivot.ext.utils.BigDecimalUtils;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;

public interface SettleService {
    BiFunction<SettleInvoiceDetail, BigDecimal, BigDecimal> settleInvoiceDetailWriteOffAmountFun = (settleInvoiceDetail, cumulative) -> BigDecimalUtils.add(settleInvoiceDetail.getWrite_off_amount(), cumulative);
    BiFunction<SettleInvoiceDetail, BigDecimal, BigDecimal> settleInvoiceDetailPlatformFun = (settleInvoiceDetail, cumulative) -> BigDecimalUtils.add(settleInvoiceDetail.getPlatformservicefee(), cumulative);
    BiFunction<SettleInvoiceDetail, BigDecimal, BigDecimal> settleInvoiceDetailInterestFun = (settleInvoiceDetail, cumulative) -> BigDecimalUtils.add(settleInvoiceDetail.getInterests(), cumulative);

    OrganizationAccountService organizationAccountService = new OrganizationAccountServiceImpl();
    TradeService tradeService = new TradeServiceImpl();
    InvoiceApplyService invoiceApplyService = new InvoiceApplyServiceImpl();
    BillService billService = new BillServiceImpl();
    InvoiceDetailBillService invoiceDetailBillService = new InvoiceDetailBillServiceImpl();
    ContractServiceFeeTemplateService contractServiceFeeTemplateService = new ContractServiceFeeTemplateServiceImpl();
    NamedParameterJdbcTemplate jdbcTemplate =  ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);


    Settle loadById(String id);

    List<Settle> loadListByIds(List<String> ids);

    /**
     * 创建销售收款单
     * @param settleInvoice
     * @return 结算单ID
     */
     String createAdvanceSettle(SettleInvoice settleInvoice);

    /**
     * 结算单作废，状态变更为已关闭Returned
     * @param id 作废结算单的ID
     */
    void cancel(String id);

    /**
     * 结算单退款
     * 退款会生成反向的结算单
     * @param settleRedInvoice 退款信息（付款账号，收款信息）
     * @param  settleReceive 原结算单
     */
    void refund(SettleRedInvoice settleRedInvoice, Settle settleReceive);

    /**
     * 结算退款-确认退款
     * @param settleIds 结算单ID
     */
    void refundConfirm(List<String> settleIds);

    /**
     * 结算退款-取消退款
     * @param settleIds 结算单ID
     */
    void refundCancel(List<String> settleIds);

    /**
     * 采购结算单确认付款
     * @param paymentList
     */
    void settlePurchasePayment(List<SettlePayment> paymentList);

    /**
     * 平台采购付款管理-已付款-取消付款
     * @param settleIds 要退款的结算单ID
     */
    String paymentCannel(List<String> settleIds);

    /**
     * 删除结算单及明细
     * @param settleId
     */
    void delete(String settleId);

    /**
     * 1、平台采购付款管理-平台付款申请单-关闭结算
     * @param settleIds 关闭的结算单ID
     * @return
     */
    String close(List<String> settleIds);

    /**
     * 订单退货，关闭关联交易的结算单(Approving,ApprovingFinance,ApprovingBusiness)
     * @param tradeIds
     */
    void closeByTrade(List<String> tradeIds);

    /**
     * 核销操作
     * @param settleInvoice
     */
    void writeOffSettle(SettleInvoice settleInvoice);

    /**
     * 取消核销
     * @param cancelIds
     */
    void writeOffSettleCancel(WriteOffCancelIds cancelIds);

    /**
     * 发票是否已经申请结算
     *
     * @param invoiceIdList 发票ID列表
     * @return false 未申请，true 已申请
     */
    boolean isInvoiceHaveSettled(List<String> invoiceIdList);


    /**
     * 回写交易的结算状态，可结算金额，客户回款状态
     * 调用点：
     * 1、销售收款核销发票
     * 2、平台采购付款提交
     * 3、平台采购确认付款
     * 4、平台采购付款关闭结算单
     * 5、据交易ID关闭结算单
     * 6、删除结算明细
     * 7、取消核销（删除结算明细）
     * 8、核销部分的退款（已作废）
     *
     * @param tradeIds 交易Id列表
     */
    void writeBackTrade(Collection<String> tradeIds);

    /**
     * 可申请结算数据展示
     * @return  可申请的结算单数据
     */
    SettleInvoice viewSettleInvoice(SettleApplyQuery settleApply);

    /**
     * 创建平台采购结算单，供应商销售收款单
     * @param settleInvoice
     */
    void createPurchaseSettle(SettleInvoice settleInvoice);

    /**
     * 采购付款审批通过，结算状态更改为待财务付款
     * @param settleIds
     */
    void approveAgree(List<String> settleIds);

    /**
     * 提交采购结算申请单
     * @param settleIds 采购结算单ID
     */
    void submit(Collection<String> settleIds);

    /**
     * 确认付款是调用
     * 根据采购付款结算单ID生成垫资服务费账单和平台费账单，以及对应发票信息
     * @param settleId 采购付款结算单ID
     * @return 服务费发票ID
     */
    List<String> generateServiceFeeBill(String settleId);

    /**
     * 根据交易id查询结算完成的金额
     *
     * @param tradeId 交易ID
     * @return 结算完成的金额
     */
    BigDecimal completedStatusSettle(String tradeId);

}
